useContext 是負責跨組件傳遞資料用, 不像是 props, 需要用參數傳遞, 在本篇會搭配 redux, 直接用程式碼去說明 context 怎麼傳遞物件
提醒:redux 觀念上可能會比較不好懂, 但算是相對精簡扼要的示範, 希望對學習的人有幫助
在下面的程式裡面
// 初始狀態 設為 null
export const initialState = null
// reducer 是一個狀態改變函數, 根據傳進來的 state 以及 action.type 去決定回傳值, 這邊只做簡單的範例示範
export const reducer = (state, action) =>{
if(action.type === "USER"){
return action.payload
}
// 這個 判斷式是寫假的, 讓讀者容易理解, redux 的用法
// 真實場景就是在上傳大頭之後, 讓顯示大頭的地方有資料
if(action.type=="UPDATEPIC"){
return{
...state,
pic:action.payload
}
}
return state
}
import EnemyList from './components/enemylist/EnemyList'
import Login from './components/login/Login'
import { Routes, Route } from "react-router-dom";
import { createContext, useReducer } from 'react';
import { reducer,initialState } from './reducer/useReducer'
// 這邊建立一個全域物件
export const UserContext = createContext()
function App() {
// 這邊使用 useReducer 將 /reducer/useReducer.js 的 initialState 跟 dispatch 引用, 變成 state 狀態, 以及 dispatch 函式, 用來更新狀態
const [state, dispatch] = useReducer(reducer,initialState)
return (
<>
{/* 這邊 UserContext.Provider 指定了 UserContext 攜帶的變數*/}
{/* 攜帶了 {state, dispatch} , 後面的 useContext 函式都會看到 */}
<UserContext.Provider value={{state, dispatch}}>
{/* 這邊為了login後的頁面跳轉做了 react router, 用法有放在參考連結*/}
<Routes>
<Route path="*" element={<Login />}></Route>
<Route path="/enemylist" element={<EnemyList/> } />
</Routes>
</UserContext.Provider>
</>
)
}
export default App
import './login.css'
import { useState, useContext} from 'react'
import { useNavigate } from 'react-router-dom'
// 引入 UserContext
import { UserContext } from '../../App'
function Login(){
// 把 state dispatch 物件拿出來
const {state, dispatch} = useContext(UserContext)
const [name, setName] = useState("")
// 這個是用來做頁面跳轉的
const navigate = useNavigate()
return (
<div className="outer">
<div> enter your name </div>
<input
className="username"
type="text"
placeholder='username'
onChange={(e)=>{
setName(e.target.value)
}}
/>
<div>
<input
className="submit"
type="button"
value="登入"
onClick={(e)=>{
// 這邊的 dispatch 就會更新觸發 reducer, 去更新 state的值
dispatch({type:"USER", payload:name})
// 頁面跳轉到 /enemylist
navigate("/enemylist")
}}
/>
</div>
</div>
)
}
export default Login
import { useState, useEffect, useContext} from 'react'
// 引入 UserContext 物件
import { UserContext } from '../../App'
import Enemy from './Enemy'
function EnemyList(){
const [enemy, setEnemy] = useState([{}])
// 取出 state dispatch 物件
const {state, dispatch} = useContext(UserContext)
useEffect(()=>{
fetch("http://localhost:8886/mock")
.then(res=>res.json())
.then(data=>{
// console.log(data)
setEnemy(data)
})
.catch(err=>{
console.log(err)
})
}, [])
return(
<>
{/* 這邊就可以使用 reactive 的 state 變數 */}
{/* 就是靠 useContext 傳遞 加上 reducer dispatch 達成的唷*/}
<h2 className="title"> {state} Challenge List </h2>
{
enemy.map((e)=>{
return (
<Enemy props = {e} key={e.id}/>
)
})
}
</>
)
}
export default EnemyList
import './enemy.css'
function Enemy(props){
// 這邊示範參數 props 傳遞
const data = {props}.props.props
return (
<>
{ console.log( data ) }
{/* 以下把 props 傳遞進來的資料, 顯示在畫面上*/}
<div className="container">
<div className="name"> Name: {data.name} </div>
<div className="name"> Job: {data.job} </div>
<div className="name"> Level: {data.level} </div>
<div className="name"> Weapon: {data.weapon} </div>
</div>
</>
)
}
export default Enemy
參考連結:
React hooks — useContext 到底怎麼用,看完這篇絕對懂!
React route—useNavigate介紹、控制history stack、傳遞參數、重新導向